package com.xy.blog.zuul.filter;

import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.xy.blog.zuul.feign.AccountServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author zanhonglei
 * @version V1.0
 * @Description:
 * @date 2019/11/23 3:55 下午
 */
@Component
public class AccessTokenFilter extends ZuulFilter {

    private static final Logger LOG = LoggerFactory.getLogger(AccessTokenFilter.class);

    @Value("#{'${ignore.url}'.split(',')}")
    private List<String> ignoreUrls;

    @Value("${capacity.name}")
    private String capacityName;

    //四种类型：pre,routing,error,post
    //pre：主要用在路由映射的阶段是寻找路由映射表的
    //routing:具体的路由转发过滤器是在routing路由器，具体的请求转发的时候会调用
    //error:一旦前面的过滤器出错了，会调用error过滤器。
    //post:当routing，error运行完后才会调用该过滤器，是在最后阶段的

    @Autowired
    private AccountServiceImpl accountService;

    @Override
    public String filterType() {
        return "pre";
    }
    /**
     * 自定义过滤器执行的顺序，数值越大越靠后执行，越小就越先执行
     * @return
     */
    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;//int值来定义过滤器的执行顺序，数值越小优先级越高
    }
    //可以在里面写一串逻辑来控制
    @Override
    public boolean shouldFilter() {
        return true;
    }
    /**
     * 执行过滤逻辑
     * @return
     */
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String url = request.getRequestURL().toString();

        if (url.contains("/v2/api-docs")) {
            return null;
        }
        String requestURI = request.getRequestURI();

        if (requestURI.contains(capacityName)) {
            return null;
        }


        LOG.info("send {} request to {}",request.getMethod(),url);
        if (ignoreUrls.contains(requestURI)) {
            return null;
        }
        String accessToken = request.getHeader("access_token");
        LOG.info("accessToken {} ",accessToken);
        if (accessToken == null || StringUtils.isEmpty(accessToken)) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
            return null;
        }
        LOG.info("accessToken {} ",accessToken);
         //验证Token
        try {
            String result = accountService.validateToken(accessToken);
            LOG.info("result {} ",result);
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (Boolean.parseBoolean(jsonObject.getString("data"))) {
                ctx.addZuulRequestHeader("token",accessToken);
            } else {
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
            }
            return null;
        } catch (Exception e) {
            LOG.error(ExceptionUtils.getStackTrace(e));
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
            return null;
        }
    }

}
